﻿using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace DotnetUtil.Md5
{
    public static class Md5Helper
    {
        public static string GetMd5String(string text)
        {
#if NET6_0_OR_GREATER
            var inputBytes = Encoding.UTF8.GetBytes(text);
            var hashBytes = MD5.HashData(inputBytes);
            return Convert.ToHexString(hashBytes);
#else
            using (var md5 = new MD5CryptoServiceProvider())
            {
                var bytes = Encoding.UTF8.GetBytes(text);
                var md5String = BitConverter.ToString(md5.ComputeHash(bytes));
                return md5String.Replace("-", "");
            }
#endif
        }

        public static async Task<string> GetFileHashAsync(string filePath)
        {
            if (string.IsNullOrWhiteSpace(filePath))
            {
                throw new ArgumentNullException(nameof(filePath));
            }

            if (!File.Exists(filePath))
            {
                throw new FileNotFoundException("文件不存在", filePath);
            }

#if NET6_0_OR_GREATER
            await using var stream = File.OpenRead(filePath);
            using var md5 = MD5.Create();
            int bytesRead;
            var buffer = new byte[4096];

            do
            {
                bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
                md5.TransformBlock(buffer, 0, bytesRead, null, 0);
            } while (bytesRead > 0);

            md5.TransformFinalBlock(buffer, 0, 0);

            var hashArray = md5.Hash?.ToArray().Select(t => t.ToString("X2").ToLower()) ?? new string[] { };
            return string.Join("", hashArray);
#else
            using (var stream = File.OpenRead(filePath))
            {
                using (var md5 = MD5.Create())
                {
                    int bytesRead;
                    var buffer = new byte[4096];

                    do
                    {
                        bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
                        md5.TransformBlock(buffer, 0, bytesRead, null, 0);
                    } while (bytesRead > 0);

                    md5.TransformFinalBlock(buffer, 0, 0);

                    var hashArray = md5.Hash.ToArray().Select(t => t.ToString("X2").ToLower());
                    return string.Join("", hashArray);
                }
            }
#endif
        }
    }
}
